home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / C++ / Applications / Nuntius 1.2 / src / Nuntius / UObjectCache.cp < prev    next >
Encoding:
Text File  |  1994-02-20  |  7.4 KB  |  331 lines  |  [TEXT/MPS ]

  1. // Copyright © 1992 Peter Speck, speck@dat.ruc.dk. All rights reserved.
  2. // UObjectCache.cp
  3.  
  4. #include "UObjectCache.h"
  5. #include "UFatalError.h"
  6.  
  7. #ifndef __STDIO__
  8. #include <stdio.h>
  9. #endif
  10.  
  11. #pragma segment MyTools
  12.  
  13. #define qDebugObjectCache qDebug & 0
  14.  
  15. TObjectCache::TObjectCache()
  16. {
  17. }
  18.  
  19. pascal void TObjectCache::Initialize()
  20. {
  21.     inherited::Initialize();
  22.     fObjectsInUseList = nil;
  23.     fFreeObjectsList = nil;
  24.     fTimeWhenCachedList = nil;
  25.     fCoHandlerInstalled = false;
  26. }
  27.  
  28. void TObjectCache::IObjectCache()
  29. {
  30.     inherited::IEventHandler(nil);
  31.     FailInfo fi;
  32.     if (fi.Try())
  33.     {
  34.         fMaxNoCachedObjects = 1 << 20;
  35.         fMaxIdleTime = kMaxIdleTime;
  36.  
  37.         fObjectsInUseList = NewList();
  38.         fFreeObjectsList = NewList();
  39.  
  40.         TLongintList *lList = new TLongintList();
  41.         lList->ILongintList();
  42.         fTimeWhenCachedList = lList;
  43.  
  44.         fi.Success();
  45.     }
  46.     else // fail
  47.     {
  48.         Free();
  49.         fi.ReSignal();
  50.     }
  51. }
  52.  
  53. pascal void TObjectCache::Free()
  54. {
  55.     if (fCoHandlerInstalled)
  56.     {
  57.         gApplication->InstallCohandler(this, false);
  58.         fCoHandlerInstalled = false;
  59.     }
  60. #if qDebugObjectCache
  61.     if (fFreeObjectsList)
  62.         fprintf(stderr, "TObjectCache::Free(), %ld idle %s's was free'd\n", fFreeObjectsList->GetSize(), GetObjectName());
  63. #endif
  64.     if (fObjectsInUseList && fObjectsInUseList->GetSize())
  65.     {
  66.         char msg[200];
  67.         sprintf(msg, "TObjectCache::Free(), Has %ld object in list of USED %s", fObjectsInUseList->GetSize(), GetObjectName());
  68.         CStr255 s(msg);
  69.         PanicExitToShell(s);
  70.     }
  71.     if (fObjectsInUseList)
  72.     {
  73.         fObjectsInUseList->FreeAll();
  74.         fObjectsInUseList->Free();
  75.         fObjectsInUseList = nil;
  76.     }
  77.     if (fFreeObjectsList)
  78.     {
  79.         fFreeObjectsList->FreeAll();
  80.         fFreeObjectsList->Free();
  81.         fFreeObjectsList = nil;
  82.     }
  83.     FreeIfObject(fTimeWhenCachedList); fTimeWhenCachedList = nil;
  84.     inherited::Free();
  85. }
  86.  
  87.  
  88. void TObjectCache::SetObjectCacheParams(long maxNoCachedObjects, long maxIdleTime)
  89. {
  90.     if (maxIdleTime != kMaxIdleTime && fCoHandlerInstalled)
  91.     {
  92.         gApplication->InstallCohandler(this, false);
  93.         fCoHandlerInstalled = false;
  94.     }
  95.     fMaxNoCachedObjects = maxNoCachedObjects;
  96.     fMaxIdleTime = maxIdleTime;
  97.     if (maxIdleTime != kMaxIdleTime)
  98.     {
  99.         fMaxIdleTime = maxIdleTime * 3 / 4;
  100.         if (!fCoHandlerInstalled)
  101.         {
  102.             gApplication->InstallCohandler(this, true);
  103.             fCoHandlerInstalled = true;
  104.         }
  105.         SetIdleFreq(maxIdleTime / 4);
  106.     }
  107.     while (fFreeObjectsList->GetSize() > maxNoCachedObjects)
  108.         DiscardObject(GetObject());
  109.     CheckIdleTime();
  110. }
  111.  
  112. void TObjectCache::FlushCache()
  113. {
  114. #if qDebugObjectCache
  115.     fprintf(stderr, "TObjectCache::FlushCache(), %ld idle %s's was free'd\n", fFreeObjectsList->GetSize(), GetObjectName());
  116. #endif
  117. #if qDebug
  118.     if (fObjectsInUseList->GetSize())
  119.     {
  120.         // we could have a flag for
  121.         // Failure, Panic or FreeThem when any in list of used objects
  122.         char msg[200];
  123.         sprintf(msg, "TLowLevelObjectCache::FlushCache(), have %ld items in list of USED %s", fObjectsInUseList->GetSize(), GetObjectName());
  124.         PanicExitToShell(msg);
  125.     }
  126. #endif
  127.     fFreeObjectsList->FreeAll();
  128. }
  129.  
  130. TObject *TObjectCache::GetObject()
  131. {
  132.     TObject *obj = nil;
  133.     VOLATILE(obj);
  134.     FailInfo fi;
  135.     if (fi.Try())
  136.     {
  137.         if (fFreeObjectsList->GetSize())
  138.         {
  139.             obj = fFreeObjectsList->Pop();
  140.             long idleTick = fTimeWhenCachedList->Pop();
  141. #if qDebugObjectCache
  142.             fprintf(stderr, "TObjectCache::GetObject(), popped %s at $%lx", GetObjectName(), long(obj));
  143.             fprintf(stderr, " from free list, was idle for %ld seconds\n", (TickCount() - idleTick) / 60);
  144. #endif
  145. #if qDebug
  146.             if (!IsObject(obj))
  147.             {
  148.                 fprintf(stderr, "Object $%lx popped from free list is not object", long(obj));
  149.                 ProgramBreak(gEmptyString);
  150.             }
  151. #endif
  152.         }
  153.         else
  154.         {
  155.             obj = CreateNewObject();
  156. #if qDebugObjectCache
  157.             fprintf(stderr, "TObjectCache::GetObject(), created new %s at $%lx\n", GetObjectName(), long(obj));
  158. #endif
  159. #if qDebug
  160.             if (!IsObject(obj))
  161.             {
  162.                 fprintf(stderr, "Created object $%lx is not object", long(obj));
  163.                 ProgramBreak(gEmptyString);
  164.             }
  165. #endif
  166.         }
  167.         fObjectsInUseList->InsertLast(obj);
  168.         fi.Success();
  169.         return obj;
  170.     }
  171.     else // fail
  172.     {
  173.         obj = FreeIfObject(obj);
  174.         fi.ReSignal();
  175.     }
  176. }
  177.  
  178. void TObjectCache::ReturnObject(TObject *obj)
  179. {
  180.     if (!obj)
  181.         return;
  182.     ArrayIndex index = fObjectsInUseList->GetIdentityItemNo(obj);
  183. #if qDebug
  184.     if (!IsObject(obj))
  185.     {
  186.         ProgramBreak("Returned obj is not object");
  187.         fObjectsInUseList->Delete(obj);
  188.         return;
  189.     }
  190. #endif
  191.     if (index == kEmptyIndex)
  192.     {
  193. #if qDebug
  194.         fprintf(stderr, "TObjectCache::ReturnObject($%lx), this obj is not in list of used obj's\n", long(obj));
  195.         ProgramBreak(gEmptyString);
  196. #endif
  197.         return;
  198.     }
  199.     fObjectsInUseList->DeleteElementsAt(index, 1);
  200. #if qDebug
  201.     ArrayIndex iii = fFreeObjectsList->GetIdentityItemNo(obj);
  202.     if (iii != kEmptyIndex)
  203.     {
  204.         fprintf(stderr, "TObjectCache::ReturnObject($%lx), this obj is in list of unused obj's with index = %ld\n", long(obj), iii);
  205.         ProgramBreak(gEmptyString);
  206.         return; // don't insert it, when it's already in list
  207.     }
  208. #endif
  209. #if qDebugObjectCache
  210.     fprintf(stderr, "TObjectCache, got returned %s at $%lx\n",GetObjectName(), long(obj));
  211. #endif
  212.     FailInfo fi;
  213.     if (fi.Try())
  214.     {
  215.         fFreeObjectsList->InsertLast(obj);
  216.         fTimeWhenCachedList->InsertLast(TickCount());
  217.         fi.Success();
  218.     }
  219.     else // fail
  220.     {
  221. #if qDebug
  222.         fprintf(stderr, "Note: could not add obj $%lx to free list (OK, just continue)", long(obj));
  223.         ProgramBreak(gEmptyString);
  224. #endif
  225.         fFreeObjectsList->Delete(obj);
  226.         obj = FreeIfObject(obj);
  227.         // we do NOT resignal here, as this can be called from a failure handler
  228.     }
  229. }
  230.  
  231. void TObjectCache::DiscardObject(TObject *obj)
  232. {
  233.     if (!obj)
  234.         return;
  235. #if qDebugObjectCache
  236.     fprintf(stderr, "TObjectCache, discarded %s at $%lx\n", GetObjectName(), long(obj));
  237. #endif
  238.     ArrayIndex index = fObjectsInUseList->GetIdentityItemNo(obj);
  239. #if qDebug
  240.     if (!IsObject(obj))
  241.     {
  242.         ProgramBreak("Discarded obj is not object");
  243.         fObjectsInUseList->Delete(obj);
  244.         return;
  245.     }
  246.     if (index == kEmptyIndex)
  247.     {
  248.         fprintf(stderr, "TObjectCache::ReturnObject($%lx), this obj is not in list of used obj's\n", long(obj));
  249.         ProgramBreak(gEmptyString);
  250.         return;
  251.     }
  252. #endif
  253.     fObjectsInUseList->DeleteElementsAt(index, 1);
  254.     FailInfo fi;
  255.     if (fi.Try())
  256.     {
  257.         obj = FreeIfObject(obj);
  258.         fi.Success();
  259.     }
  260.     else // fail
  261.     {
  262. #if qDebug
  263.         fprintf(stderr, "Got signal when free'ing discarded %s\n", GetObjectName());
  264.         ProgramBreak(gEmptyString);
  265. #endif
  266.     }
  267. }
  268.  
  269. pascal Boolean TObjectCache::DoIdle(IdlePhase phase)
  270. {
  271.     CheckIdleTime();
  272.     return inherited::DoIdle(phase);
  273. }
  274.  
  275. void TObjectCache::CheckIdleTime()
  276. {
  277.     long tc = TickCount();
  278.     long oldTick = tc - fMaxIdleTime;
  279.     for (ArrayIndex index = fTimeWhenCachedList->GetSize(); index; index--)
  280.     {
  281.         long cacheTime = fTimeWhenCachedList->At(index);
  282.         if (cacheTime < oldTick)
  283.         {
  284.             TObject *obj = fFreeObjectsList->At(index);
  285. #if qDebugObjectCache
  286.             fprintf(stderr, "TObjectCache, Free's expired %s at $%lx, idle time = %ld seconds\n",
  287.                 GetObjectName(), long(obj), (tc - cacheTime) / 60);
  288.             if (!IsObject(obj))
  289.                 ProgramBreak("The obj is not object");
  290. #endif
  291.             FailInfo fi;
  292.             if (fi.Try())
  293.             {
  294.                 obj = FreeIfObject(obj);
  295.                 fi.Success();
  296.             }
  297.             else // fail
  298.             {
  299. #if qDebug
  300.                 ProgramBreak("Failed in free of expired cached object");
  301. #endif
  302.             }
  303.             fFreeObjectsList->DeleteElementsAt(index, 1);
  304.             fTimeWhenCachedList->DeleteElementsAt(index, 1);
  305.         }
  306.     } // for
  307. }
  308.  
  309. TObject *TObjectCache::CreateNewObject()
  310. {
  311.     SubClassResponsibility();
  312.     return nil;
  313. }
  314.  
  315. const char *TObjectCache::GetObjectName()
  316. {
  317.     SubClassResponsibility();
  318.     return "TObject";
  319. }
  320.  
  321. long TObjectCache::GetNoCachedObjects()
  322. {
  323.     return fFreeObjectsList->GetSize();
  324. }
  325.  
  326. long TObjectCache::GetNoActiveObjects()
  327. {
  328.     return fObjectsInUseList->GetSize();
  329. }
  330.  
  331.